/**
 * 创建人：陈征
 * 创建日期：Apr 13, 2010 2:39:11 PM
 * 说明：
 */

package com.umpay.privi.helper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.umpay.privi.common.ReqMessage;
import com.umpay.privi.common.ResMessage;
import com.umpay.privi.common.RetCode;
import com.umpay.privi.common.XmlData;
import com.umpay.privi.exception.BusinessException;
import com.umpay.privi.util.CheckReqDataUtil;
import com.umpay.privi.util.EhcacheUtil;
import com.umpay.privi.util.PropertiesUtil;
import com.umpay.privi.util.StringUtil;


/**
 */
public class ReqParaCheckHelper {

	private static Logger imlog = LoggerFactory.getLogger(ReqParaCheckHelper.class);
	private static Cache cache= EhcacheUtil.getCache(EhcacheUtil.CACHE_NAME_RULE,ReqParaCheckHelper.class);
	
	/**
	 * 用于校验请求参数完整性 规则在checkRule.properties文件配置
	 * @param req
	 * @param ruleId 
	 * @return
	 */
	public static ResMessage checkRequire(ReqMessage req,String ruleId){
		imlog.info("开始校验参数完整性,规则="+ruleId);
		ResMessage res = new ResMessage();
		res.setRpid(req.getRpid());
		res.setRetCode(RetCode.SUCCESS);
		res.setRetMsg("参数校验通过");
		
		if (StringUtil.isEmpty(ruleId)) {
			imlog.warn(String.format("校验规则未传入"));
			return res;
		}
		
		// 对每个key进行正则表达式校验
        String[] rules = loadRuleFromCache(ruleId);
        
        for(String key:rules){
        	key = StringUtil.trim(key);
    		if (StringUtil.isEmpty(key)) {
    			//key为空，则校验下一个
    			continue;
    		}
    		
    		boolean must = true;
    		if (CheckReqDataUtil.isOptional(key)) {
    			key = CheckReqDataUtil.removBrackets(key);
    			must = false;
    		} 
    		
    		try {
				check(key, req.get(key), must);
			} catch (BusinessException e) {
				imlog.error(e.getMessage());
				res.setRetCode(e.getCode());
				res.setRetMsg(e.getMessage());
				return res;
			}
		}
        
		imlog.info("参数完整性校验结果"+res.getRetMsg());
		return res;
	}
	
	public static void check(String key, Object value, boolean must) throws BusinessException {
		if (!(value instanceof String)) {
			//如果参数不是字符串类型，只判断参数值是否为空
			if (must && null == value) {
				throw new BusinessException(RetCode.REQ_PARA_MISSING, String.format("必传字段%s为空", key));
			} else {
				return;
			}
		}
		
		String valueStr = (String)value;//将参数转换为字符串类型
		
		if (StringUtil.isEmpty(valueStr)) {
			if (must) {
				throw new BusinessException(RetCode.REQ_PARA_MISSING, String.format("必传字段%s为空", key));
			}
		} else {
			//输入参数格式、长度校验
			String regex = PropertiesUtil.getValue("Regex." + key);
			String length = PropertiesUtil.getValue("Regex." + key + ".length");
			if (StringUtil.isEmpty(regex)) {
				imlog.warn(String.format("请求参数 %s未配置格式校验规则", key));
				return;
			}
            if (!valueStr.matches(regex)) {
            	throw new BusinessException(RetCode.REQ_PARA_NOT_MATCH, String.format("请求参数%s[%s]不能匹配regex[%s]", key, value, regex));
            }
			if (StringUtil.isEmpty(length)) {
				imlog.warn(String.format("请求参数 %s未配置长度校验规则", key));
				return;
			}
            try {
				if (valueStr.getBytes("GBK").length > Integer.valueOf(length)) {
					throw new BusinessException(RetCode.REQ_PARA_NOT_MATCH, String.format("请求参数%s[%s]超出最大长度[%s]", key, value, length));
				}
			} catch (Exception e) {
				throw new BusinessException(RetCode.REQ_PARA_NOT_MATCH, String.format("请求参数%s[%s]不能匹配regex[%s]", key, value, regex));
			} 
		}
		return;
	}
	
	/**
	 * desc: 校验map请求参数
	 * <p>创建人：Ding Zhe , Sep 7, 2012 2:20:14 PM</p>
	 * @param keys 
	 * @param reqMap
	 * @throws Exception
	 */
	public static boolean doCheck(String ruleId, Map<String, String> reqMap) throws Exception {
		if (StringUtil.isEmpty(ruleId)) {
			return true;
		}
		String keys = PropertiesUtil.getValue(ruleId);
		if (StringUtil.isEmpty(keys)) {
			imlog.info(String.format("Check ruleId %s found no check info", ruleId));
            return true;
		}
		// 对每个key进行正则表达式校验
        String[] rules = loadRuleFromCache(ruleId);
        
        for(String key:rules){
        	key = StringUtil.trim(key);
    		if (StringUtil.isEmpty(key)) {
    			continue;
    		}
    		
    		boolean must = true;
    		if (CheckReqDataUtil.isOptional(key)) {
    			key = CheckReqDataUtil.removBrackets(key);
    			must = false;
    		} 
    		if (!CheckReqDataUtil.check(key, reqMap.get(key), must)) {
    			imlog.error(String.format("Request Parameter %s can not match", key));
    			return false;
			}
    		
		}
        return true;
	}
	
	private static String[] loadRuleFromCache(String ruleId){
		String[] retVal = new String[]{} ;
		Element e = cache.get(ruleId);
		if (null != e && !e.isExpired()) {
			retVal = (String[])e.getValue();
		} else {
			String rule = PropertiesUtil.getValue(ruleId);
			if(null !=rule){
				String[]temp = rule.split(",");
				if(temp.length>0){
					List<String> list = new ArrayList<String>();
					for(String str:temp){
						str = str.trim();
						if(str.length()>0){
							list.add(str);
						}
					}
					retVal = list.toArray(new String[list.size()]);
					
				}
			} else {
				imlog.info(String.format("校验规则%s未配置", ruleId));
			}
		}
		
		return retVal;
	}

	
	public static void main(String[] args) {
		ReqMessage reqMessage = new ReqMessage();
		Map<String, Object> reqMap = new HashMap<String, Object>();
		reqMap.put(XmlData.MERID, "werwer");
		reqMap.put(XmlData.EMAIL, "dingzhe@umpay.com");
		reqMap.put(XmlData.MOBILEID, "阿斯顿发水电费4");
		reqMap.put(XmlData.LOGNAME, "9996");
		List<Integer> roleList = new ArrayList<Integer>();
		roleList.add(new Integer(1));
		roleList.add(new Integer(2));
		roleList.add(new Integer(3));
		reqMap.put(XmlData.ROLE_LIST, roleList);
		reqMessage.putAll(reqMap);
		
		System.out.println(checkRequire(reqMessage, "CrmQryServiceBean.queryOpenAccBankByMerId.require"));
	}
}
